#ifndef _MATHEMATICS_ALGEBRA_EQUATION_
#define _MATHEMATICS_ALGEBRA_EQUATION_

#include "expression_fraction.h"
#include "..\..\utilities\string_helper.h"
using namespace science::utilities;

#include <iostream>
#include <math.h>

namespace science
{
	namespace mathematics
	{
		namespace algebra
		{
			class equation
			{
			protected:
				expression_fraction _lhs;
				expression_fraction _rhs;

			public:
				equation()
				{
					
				}

				equation(expression_fraction lhs, expression_fraction rhs)
				{
					_lhs = lhs.simplify();
					_rhs = rhs.simplify();
				}

				equation(std::string equation_str)
				{
					unsigned int index = 0;
					*this = parse_equation(equation_str, index);
				}

				virtual ~equation()
				{

				}

			public:
				expression_fraction& get_lhs() { return _lhs; }
				expression_fraction& get_rhs() { return _rhs; }
				void set_lhs(expression_fraction lhs) { _lhs = lhs; }
				void set_rhs(expression_fraction rhs) { _rhs = rhs; }

			public:
				bool check_solution(std::map<char, double> var_values)
				{
					if (math_helper::double_check(_lhs.evaluate(var_values), _rhs.evaluate(var_values)) == 0)
						return true;
					return false;
				}

				equation simplify()
				{
					equation eq = *this;
					eq._lhs = eq._lhs.simplify();
					eq._rhs = eq._rhs.simplify();
					return eq;
				}

				virtual set<set<double>> solve()
				{
					return set<set<double>>();
				}

			public:
				friend std::ostream &operator<<(std::ostream &output, const equation &eq)
				{
					output << eq._lhs << " = " << eq._rhs;
					return output;
				}

				friend std::istream &operator>>(std::istream  &input, equation &eq)
				{
					std::cout << "Enter LHS : " << std::endl;
					input >> eq._lhs;
					std::cout << "Enter RHS : " << std::endl;
					input >> eq._rhs;

					eq = eq.simplify();

					return input;
				}

			public:
				static equation parse_equation(std::string str, unsigned int& index)
				{
					str = string_helper::remove_white_chars(str);
					equation exp;
					if (index >= str.size())
						return exp;

					exp.set_lhs(expression_fraction::parse_expression_fraction(str, index));
					if (str[index] == '=')
					{
						index++;
						if (index >= str.size())
							throw new std::invalid_argument("Invalid equation string");
						exp.set_rhs(expression_fraction::parse_expression_fraction(str, index));
					}
					else
						throw new std::invalid_argument("Invalid equation string");

					return exp;
				}
			};
		}
	}
}

#endif